<?php
/**
 * 1.php
 * Created by PhpStorm.
 * User: 江小波
 * Date: 2018/11/20
 * Time: 15:55
 */

/**
 * 观察者模式：目标(Subject)和多个观察者(Observer)两种角色；目标角色发送变化需要通知多个观察者
 * SPL 提供 SplSubject 、 SplObserver 、 SplObjectStorage
 * 需求：用户改变密码的时候，通过不同的方式推送给用户（比如邮件、短信、站内信）
 * 1 : n 的依赖关系，适合用观察者模式
 */

/**
 * 编写一个目标类 实现 SplSubject 接口
 * 需要实现的方法有三个：attach、detach、notify
 * Class User
 */
class User implements SplSubject {

    private $email;
    private $username;
    private $mobile;
    private $password;

    private $observers = null;

    public function __construct(){
        /**
         * 实现对象存储的功能的SPL类，而且保证了同一个实例的唯一性，不会重复存储相同对象实例
         */
        $this->observers = new SplObjectStorage();
    }

    /**
     * 添加（注册）一个观察者
     * @param SplObserver $observer
     */
    public function attach(SplObserver $observer){
        $this->observers->attach($observer);
    }

    /**
     * 删除一个观察者
     * @param SplObserver $observer
     */
    public function detach(SplObserver $observer){
        $this->observers->detach($observer);
    }

    /**
     * 当状态发送改变时候，通知所有观察者
     */
    public function notify(){
        $userInfo = [
            'email' => $this->email,
            'username' => $this->username,
            'mobile' => $this->mobile,
            'password' => $this->password
        ];
        foreach($this->observers as $observer){
            $observer->update($this,$userInfo);
        }
    }

    /**
     * 创建用户时候，分配
     */
    public function create($email,$username,$mobile,$password){
        echo __METHOD__, PHP_EOL;

        $this->email = $email;
        $this->username = $username;
        $this->mobile = $mobile;
        $this->password = $password;

        $this->notify();
    }
    /**
     * 重置密码
     */
    public function resetPassword(){
        echo __METHOD__, PHP_EOL;

        $this->password = mt_rand(100000, 999999);
        $this->notify();
    }
    /**
     * 修改密码
     */
    public function changePassword($newPassword){
        echo __METHOD__, PHP_EOL;

        $this->password = $newPassword;
        $this->notify();
    }
}

/**
 * 当用户密码更改时候，短信推送类
 * Class MobileSender
 */
class MobileSender implements SplObserver {
    public function update(SplSubject $subject){
        if(func_num_args() === 2){
            $userInfo = func_get_arg(1);
            echo "向 {$userInfo['mobile']} 发送短信成功。内容是：你好 {$userInfo['username']}" .
                "你的新密码是 {$userInfo['password']}，请妥善保管", PHP_EOL;
        }
    }
}
/**
 * 当用户密码更改时候，邮件推送类
 * Class EmailSender
 */
class EmailSender implements SplObserver {
    public function update(SplSubject $subject){
        if(func_num_args() === 2){
            $userInfo = func_get_arg(1);
            echo "向 {$userInfo['email']} 发送电子邮件成功。内容是：你好 {$userInfo['username']}" .
                "你的新密码是 {$userInfo['password']}，请妥善保管", PHP_EOL;
        }
    }
}
/**
 * 当用户密码更改时候，站内信推送类
 * Class WebSender
 */
class WebSender implements SplObserver {
    public function update(SplSubject $subject){
        if(func_num_args() === 2){
            $userInfo = func_get_arg(1);
            echo "你好 {$userInfo['username']}" .
                "你的新密码是 {$userInfo['password']}，请妥善保管", PHP_EOL;
        }
    }
}

header("Content-type: text/html; charset=utf-8");
echo "-----------------------【1】-----------------------", PHP_EOL;

$mobileSender = new MobileSender();
$emailSender = new EmailSender();
$webSender = new WebSender();

$user = new User();
/**
 * 创建用户，需要推送短信、邮件、站内信
 */
$user->attach($mobileSender);
$user->attach($emailSender);
$user->attach($webSender);
$user->create('420092586@qq.com','江小波','18883870892','123456');

/**
 * 重置密码，只需要推送站内信
 */
$user->detach($mobileSender);
$user->detach($emailSender);
$user->resetPassword();

/**
 * 修改密码，只需要推送短信、2条邮件
 */
$user->attach($mobileSender);
$user->attach($emailSender);
$user->attach(new EmailSender());
$user->detach($webSender);
$user->changePassword('654321');

$order_sn = '20181114152438571405';
echo strlen($order_sn),"\t",$order_sn,PHP_EOL;
$order_sn .= mt_rand(1000,9999);
echo strlen($order_sn),"\t",$order_sn,PHP_EOL;
$order_sn = substr($order_sn,0,20);
echo strlen($order_sn),"\t",$order_sn,PHP_EOL;
// 设置时区为北京时间
//date_default_timezone_set('PRC');
//echo '---------------------', PHP_EOL;
//$sql = [];
//for($i=1;$i<=11;$i++){
//    $s_time = mktime(0,0,0,$i,1,2018);
//    $e_time = mktime(0,0,0,$i+1,0,2018);
//    $s_date = date('Y-m-d H:i:s',$s_time);
//    $e_date = date('Y-m-d H:i:s',$e_time);
//    echo $s_time,"\t",$s_date,$e_time,"\t",$e_date, PHP_EOL;
//    $sql[] = "SELECT '{$i}月份' as `月份`, (SUM(subtotal)/10) as `成交总金额（元）`, count(*) as `订单总量` FROM newerp_jifen_order
//WHERE `pay_status`=1 AND `status`=1 AND add_time>{$s_time} AND add_time<{$e_time}";
//}
//
//echo "------------",PHP_EOL;
//echo implode(' union ',$sql);
